# -*- coding: utf-8 -*-
# @Time    : 2020/3/17 下午8:19
# @Author  : lilong

"""
1.p = Person(name, age)
2.首先执行使用name和age参数来执行Person类的new方法，这个new方法会
    返回Person类的一个实例（通常情况下是使用 super(Persion, cls).new(cls, … …) 这样的方式），
3.然后利用这个实例来调用类的init方法，上一步里面new产生的实例也就是__init__里面的的 self

所以，init 和 new 最主要的区别在于：
1. init 通常用于初始化一个新实例，控制这个初始化的过程，比如添加一些属性， 做一些额外的操作，发生在类实例被创建完以后。它是实例级别的方法。
2. new 通常用于控制生成一个新实例的过程。它是类级别的方法。
3. new至少要有一个参数cls，代表要实例化的类，此参数在实例化时由Python解释器自动提供
4. new必须要有返回值，返回实例化出来的实例，这点在自己实现new时要特别注意，可以return父类new出来的实例，或者直接是object的new出来的实例
5. 可以将类比作制造商，new方法就是前期的原材料购买环节，init方法就是在有原材料的基础上，加工，初始化商品环节
"""


class Person(object):

    def __new__(cls,  *args, **kwargs):
        print('__new__ called.')
        return super(Person, cls).__new__(cls)

    def __init__(self, name, age):
        print('__init__ called.')
        self.name = name
        self.age = age

    def __str__(self):
        return '<Person: %s(%s)>' % (self.name, self.age)


class PositiveInteger(int):
    def __init__(self, value):
        super(PositiveInteger, self).__init__(self, abs(value))


i = PositiveInteger(-3)
print(i)
# 但运行后会发现，结果根本不是我们想的那样，我们任然得到了-3。
# 这是因为对于int这种 不可变的对象，我们只有重载它的new方法才能起到自定义的作用,如下：

"""
class PositiveInteger(int):
    def __new__(cls, value):
        return super(PositiveInteger, cls).__new__(cls, abs(value))
"""


if __name__ == '__main__':
    name = Person('xxx', 24)
    print(name)
